/*
 * Module:	EEPROM driver
 * Author:	Lvjianfeng
 * Date:	2011.12
 */


#include "stm8l15x.h"

#include "drv.h"


//Constant definition

#define I2C_CLOCK					320000

#define EEPROM_DEVICE_ADDRESS		0xA0
#define EEPROM_PAGE_SIZE			128
#define EEPROM_PAGE_ADDRESS_MASK	0xFF80
#define EEPROM_TIME_OUT				5000


//Type definition

typedef enum
{
	DRV_EEPROM_FLAG_READ_ONGOING = 0,
	DRV_EEPROM_FLAG_ENABLE,
	DRV_EEPROM_COUNT_FLAG
} drv_eeprom_flag;


//Private variable definition

static volatile uint m_ui_Flag = {0};
static uint16 m_u16_Timeout = {0};


//Private function declaration

void DrvEEPROM_Config(void);
uint DrvEEPROM_PollWriteDone(void);


//Public function definition

uint DrvEEPROM_Initialize(void)
{
	CLK->PCKENR1 |= CLK_PCKENR1_I2C1;

	return FUNCTION_OK;
}


uint DrvEEPROM_SetConfig
(
	uint ui_Parameter,
	const uint8 *u8p_Value,
	uint ui_Length
)
{

	return FUNCTION_OK;
}


uint DrvEEPROM_GetConfig
(
	uint ui_Parameter,
	uint8 *u8p_Value,
	uint *uip_Length
)
{
	switch (ui_Parameter)
	{
		case DRV_EEPROM_PARAM_SWITCH:

			if (REG_GET_BIT(m_ui_Flag, DRV_EEPROM_FLAG_ENABLE) != 0)
			{
				*((uint *)u8p_Value) = 1;
			}
			else
			{
				*((uint *)u8p_Value) = 0;
			}

			break;

		default:
			break;
	}

	return FUNCTION_OK;
}


uint DrvEEPROM_Write
(
	uint32 u32_Address,
	const uint8 *u8p_Data,
	uint16 u16_Length
)
{
	uint16 u16_PageLength;


	DrvEEPROM_Enable();
	u16_PageLength = ((uint16)u32_Address & EEPROM_PAGE_ADDRESS_MASK) + 
			EEPROM_PAGE_SIZE - (uint16)u32_Address;

	if (u16_PageLength > u16_Length)
	{
		u16_PageLength = u16_Length;
	}

	while (u16_Length > 0)
	{
		Drv_DisableInterrupt();
		m_u16_Timeout = 0;

		/*!< While the bus is busy */
		while ((I2C1->SR3 & I2C_SR3_BUSY) != 0)
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send START condition */
		I2C1->CR2 |= I2C_CR2_START;
		m_u16_Timeout = 0;

		/*!< Test on EV5 and clear it */
		while (((I2C1->SR1 & I2C_SR1_SB) != I2C_SR1_SB) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send EEPROM address for write */
		I2C1->DR = EEPROM_DEVICE_ADDRESS & ~(0x01);
		m_u16_Timeout = 0;

		/*!< Test on EV6 and clear it */
		while (((I2C1->SR1 & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 
			(I2C_SR1_ADDR | I2C_SR1_TXE)) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send the higher byte of address to be written */
		I2C1->DR = (uint8)(u32_Address >> 8);
		m_u16_Timeout = 0;

		/*!< Test on EV8 and clear it */
		while (((I2C1->SR1 & (I2C_SR1_BTF | I2C_SR1_TXE)) != 
			(I2C_SR1_BTF | I2C_SR1_TXE)) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send the lower byte of address to be written */
		I2C1->DR = (uint8)u32_Address;
		m_u16_Timeout = 0;

		/*!< Test on EV8 and clear it */
		while (((I2C1->SR1 & (I2C_SR1_BTF | I2C_SR1_TXE)) != 
			(I2C_SR1_BTF | I2C_SR1_TXE)) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		u16_Length -= u16_PageLength;
		u32_Address += (uint32)u16_PageLength;

		while (u16_PageLength > 0)
		{
			/*!< Send the byte to be written */
			if (u8p_Data != (const uint8 *)0)
			{
				I2C1->DR = *u8p_Data;
			}
			else
			{
				I2C1->DR = DRV_EEPROM_ERASED_DATA;
			}

			m_u16_Timeout = 0;

			/*!< Test on EV8 and clear it */
			while (((I2C1->SR1 & (I2C_SR1_BTF | I2C_SR1_TXE)) != 
				(I2C_SR1_BTF | I2C_SR1_TXE)) ||
				((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
				(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
			{
				m_u16_Timeout++;

				if (m_u16_Timeout > EEPROM_TIME_OUT)
				{
					Drv_EnableInterrupt();
					return FUNCTION_FAIL;
				}
			}

			u16_PageLength--;

			if (u8p_Data != (const uint8 *)0)
			{
				u8p_Data++;
			}
		}

		/*!< Send STOP condition */
		I2C1->CR2 |= I2C_CR2_STOP;

		if (u16_Length > EEPROM_PAGE_SIZE)
		{
			u16_PageLength = EEPROM_PAGE_SIZE;
		}
		else
		{
			u16_PageLength = u16_Length;
		}

		Drv_EnableInterrupt();

		if (DrvEEPROM_PollWriteDone() != FUNCTION_OK)
		{
			return FUNCTION_FAIL;
		}
	}

	DrvEEPROM_Disable();

	return FUNCTION_OK;
}


uint DrvEEPROM_Read
(
	uint32 u32_Address,
	uint8 *u8p_Data,
	uint16 *u16p_Length
)
{
	uint16 u16_Length;
	uint16 u16_PageLength;


	DrvEEPROM_Enable();
	u16_Length = *u16p_Length;
	u16_PageLength = ((uint16)u32_Address & EEPROM_PAGE_ADDRESS_MASK) + 
			EEPROM_PAGE_SIZE - (uint16)u32_Address;

	if (u16_PageLength > u16_Length)
	{
		u16_PageLength = u16_Length;
	}

	while (u16_Length > 0)
	{
		Drv_DisableInterrupt();
		m_u16_Timeout = 0;

		/*!< While the bus is busy */
		while ((I2C1->SR3 & I2C_SR3_BUSY) != 0)
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send START condition */
		I2C1->CR2 |= I2C_CR2_START;
		m_u16_Timeout = 0;

		/*!< Test on EV5 and clear it */
		while (((I2C1->SR1 & I2C_SR1_SB) != I2C_SR1_SB) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send EEPROM address for read */
		I2C1->DR = EEPROM_DEVICE_ADDRESS & ~(0x01);
		m_u16_Timeout = 0;

		/*!< Test on EV6 and clear it */
		while (((I2C1->SR1 & (I2C_SR1_ADDR | I2C_SR1_TXE)) != 
			(I2C_SR1_ADDR | I2C_SR1_TXE)) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send the higher byte of address to be read */
		I2C1->DR = (uint8)(u32_Address >> 8);
		m_u16_Timeout = 0;

		/*!< Test on EV8 and clear it */
		while (((I2C1->SR1 & (I2C_SR1_BTF | I2C_SR1_TXE)) != 
			(I2C_SR1_BTF | I2C_SR1_TXE)) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send the lower byte of address to be read */
		I2C1->DR = (uint8)u32_Address;
		m_u16_Timeout = 0;

		/*!< Test on EV8 and clear it */
		while (((I2C1->SR1 & (I2C_SR1_BTF | I2C_SR1_TXE)) != 
			(I2C_SR1_BTF | I2C_SR1_TXE)) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY | I2C_SR3_TRA)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send STRAT condition a second time */
		I2C1->CR2 |= I2C_CR2_START;
		m_u16_Timeout = 0;

		/*!< Test on EV5 and clear it */
		while (((I2C1->SR1 & I2C_SR1_SB) != I2C_SR1_SB) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/*!< Send EEPROM address for read */
		I2C1->DR = EEPROM_DEVICE_ADDRESS | 0x01;
		m_u16_Timeout = 0;

		/*!< Test on EV6 and clear it */
		while (((I2C1->SR1 & I2C_SR1_ADDR) != I2C_SR1_ADDR) ||
			((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY)) != 
			(I2C_SR3_MSL | I2C_SR3_BUSY)))
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				Drv_EnableInterrupt();
				return FUNCTION_FAIL;
			}
		}

		/* If number of data to be read is 1, then DMA couldn't be used */
		if (u16_PageLength == 1)
		{
			/*!< Disable Acknowledgement */
			I2C1->CR2 &= ~I2C_CR2_ACK;

			/*!< Send STOP Condition */
			I2C1->CR2 |= I2C_CR2_STOP;
			m_u16_Timeout = 0;

			/*!< Test on EV7 and clear it */
			while (((I2C1->SR1 & I2C_SR1_RXNE) != I2C_SR1_RXNE) ||
				((I2C1->SR3 & (I2C_SR3_MSL | I2C_SR3_BUSY)) != 
				(I2C_SR3_MSL | I2C_SR3_BUSY)))
			{
				m_u16_Timeout++;

				if (m_u16_Timeout > EEPROM_TIME_OUT)
				{
					Drv_EnableInterrupt();
					return FUNCTION_FAIL;
				}
			}

			/*!< Read a byte from the EEPROM */
			*u8p_Data = I2C1->DR;

			/*!< Enable Acknowledgement to be ready for another reception */
			I2C1->CR2 |= I2C_CR2_ACK;
			
			Drv_EnableInterrupt();
		}
		/* DMA could be used for number of data higher than 1 */
		else
		{
			REG_SET_BIT(m_ui_Flag, DRV_EEPROM_FLAG_READ_ONGOING);

			/* Disable the selected DMA Channelx */
			DMA1_Channel0->CCR &= ~DMA_CCR_CE;

			/* Reset DMA Channelx control register */
			DMA1_Channel0->CCR = DMA_CCR_RESET_VALUE;

			/* Set DMA direction & Mode & Incremental Memory mode */
			DMA1_Channel0->CCR |= DMA_CCR_IDM;

			/*Clear old priority and memory data size  option */
			DMA1_Channel0->CSPR &= ~(DMA_CSPR_PL);

			/* Set old priority and memory data size  option */
			DMA1_Channel0->CSPR |= 0x20;

			/* Write to DMA Channelx CNDTR */
			DMA1_Channel0->CNBTR = (uint8)u16_PageLength;

			/* Write to DMA Channelx (0, 1 or 2)  Peripheral address  or  Write to 
			   DMA Channel 3 Memory 1 address  */
			DMA1_Channel0->CPARH = (uint8)((uint32)&I2C1->DR >> 8);
			DMA1_Channel0->CPARL = (uint8)((uint32)&I2C1->DR);

			/* Write to DMA Channelx Memory address */
			DMA1_Channel0->CM0ARH = (uint8)((uint32)u8p_Data >> 8);
			DMA1_Channel0->CM0ARL = (uint8)((uint32)u8p_Data);

			DMA1_Channel0->CSPR &= ~DMA_CSPR_TCIF;
			DMA1_Channel0->CCR |= DMA_ITx_TC;
			DMA1_Channel0->CCR |= DMA_CCR_CE;

			Drv_EnableInterrupt();
			m_u16_Timeout = 0;

			while (REG_GET_BIT(m_ui_Flag, DRV_EEPROM_FLAG_READ_ONGOING) != 0)
			{
				m_u16_Timeout++;

				if (m_u16_Timeout > EEPROM_TIME_OUT)
				{
					return FUNCTION_FAIL;
				}
			}
		}

		u16_Length -= u16_PageLength;
		u32_Address += (uint32)u16_PageLength;
		u8p_Data += u16_PageLength;

		if (u16_Length > EEPROM_PAGE_SIZE)
		{
			u16_PageLength = EEPROM_PAGE_SIZE;
		}
		else
		{
			u16_PageLength = u16_Length;
		}
	}

	DrvEEPROM_Disable();

	return FUNCTION_OK;
}


uint DrvEEPROM_Erase
(
	uint32 u32_Address,
	uint16 u16_Length
)
{
	return DrvEEPROM_Write(u32_Address, (const uint8 *)0, u16_Length);
}


void DrvEEPROM_Enable(void)
{
	if (REG_GET_BIT(m_ui_Flag, DRV_EEPROM_FLAG_ENABLE) == 0)
	{
		Drv_EnablePower();
		I2C1->CR2 |= I2C_CR2_SWRST;
		I2C1->CR2 &= ~I2C_CR2_SWRST;
		DrvEEPROM_Config();
		REG_SET_BIT(m_ui_Flag, DRV_EEPROM_FLAG_ENABLE);
	}
}


void DrvEEPROM_Disable(void)
{
	REG_CLEAR_BIT(m_ui_Flag, DRV_EEPROM_FLAG_ENABLE);
	Drv_DisablePower();
}


void DrvEEPROM_Interrupt(void)
{
	/*!< Send STOP Condition */
	I2C1->CR2 |= I2C_CR2_STOP;

	REG_CLEAR_BIT(m_ui_Flag, DRV_EEPROM_FLAG_READ_ONGOING);
}


#if DRV_EEPROM_TEST_ENABLE == 1

#include "lib_checksum.h"

void DrvEEPROM_Test(void)
{
	uint16 u16_Code1[] = {999, 210, 70, 70, 10, 35};
	sint32 s32_Code2[] = {509422, 3747972, 452177, -21259, 0, 
		1320, 1692, 2577, -991, 1860, 56890};
	uint16 u16_Code3[35] = {0};
	sint32 s32_Code4[] = {100000, 1681, 11, 100000, 2041, 11, 
		10905, 52863, 11908, 44731, 
		-200284, 1885, -2, -136335, 2025, 24, 
		-2453536, 1053755, -109836, 
		42000};
	uint16 u16_Code5[23] = {0};
	uint16 u16_Checksum;
	uint16 u16_ChecksumHCT;
	uint8 u8_Data[256] = {0};
	uint16 u16_Length;
	uint32 u32_Address = 0x80;

	u16_Checksum = LibChecksum_GetChecksum16Bit((const uint8 *)u16_Code1, 
		sizeof(u16_Code1));
	u16_Checksum = LibChecksum_GetChecksumPartial16Bit((const uint8 *)s32_Code2, 
		sizeof(s32_Code2), u16_Checksum);
	u16_Checksum = LibChecksum_GetChecksumPartial16Bit((const uint8 *)u16_Code3, 
		sizeof(u16_Code3), u16_Checksum);
	u16_ChecksumHCT = LibChecksum_GetChecksum16Bit((const uint8 *)s32_Code4, 
		sizeof(s32_Code4));
	u16_ChecksumHCT = LibChecksum_GetChecksumPartial16Bit((const uint8 *)u16_Code5, 
		sizeof(u16_Code5), u16_ChecksumHCT);


	do
	{
		Drv_EnablePower();
		DrvEEPROM_Enable();

		if (DrvEEPROM_Write(u32_Address, (const uint8 *)u16_Code1, sizeof(u16_Code1)) != 
			FUNCTION_OK)
		{
			break;
		}

		if (DrvEEPROM_Write(u32_Address + sizeof(u16_Code1), (const uint8 *)s32_Code2, 
			sizeof(s32_Code2)) != FUNCTION_OK)
		{
			break;
		}

		if (DrvEEPROM_Write(u32_Address + sizeof(u16_Code1) + sizeof(s32_Code2), (const uint8 *)u16_Code3, 
			sizeof(u16_Code3)) != FUNCTION_OK)
		{
			break;
		}

		if (DrvEEPROM_Write(u32_Address + sizeof(u16_Code1) + sizeof(s32_Code2) + sizeof(u16_Code3), 
			(const uint8 *)&u16_Checksum, sizeof(u16_Checksum)) != FUNCTION_OK)
		{
			break;
		}

		if (DrvEEPROM_Write(u32_Address + sizeof(u16_Code1) + sizeof(s32_Code2) + sizeof(u16_Code3) +
			sizeof(u16_Checksum), 
			(const uint8 *)s32_Code4, sizeof(s32_Code4)) != FUNCTION_OK)
		{
			break;
		}

		if (DrvEEPROM_Write(u32_Address + sizeof(u16_Code1) + sizeof(s32_Code2) + sizeof(u16_Code3) +
			sizeof(u16_Checksum) + sizeof(s32_Code4), 
			(const uint8 *)u16_Code5, sizeof(u16_Code5)) != FUNCTION_OK)
		{
			break;
		}

		if (DrvEEPROM_Write(u32_Address + sizeof(u16_Code1) + sizeof(s32_Code2) + sizeof(u16_Code3) +
			sizeof(u16_Checksum) + sizeof(s32_Code4) + sizeof(u16_Code5), 
			(const uint8 *)&u16_ChecksumHCT, sizeof(u16_ChecksumHCT)) != FUNCTION_OK)
		{
			break;
		}

		u16_Length = sizeof(u8_Data);
		if (DrvEEPROM_Read(u32_Address, u8_Data, &u16_Length) != FUNCTION_OK)
		{
			break;
		}

		DrvEEPROM_Disable();
		Drv_DisablePower();
/*		if (DrvEEPROM_Write(0x05, u8_Data, sizeof(u8_Data)) != FUNCTION_OK)
		{
			break;
		}

		u16_Length = 4;

		if (DrvEEPROM_Read(0x00, u8_Data, &u16_Length) != FUNCTION_OK)
		{
			break;
		}

		u16_Length = 4;

		if (DrvEEPROM_Read(0x03, u8_Data, &u16_Length) != FUNCTION_OK)
		{
			break;
		}

		u16_Length = 4;

		if (DrvEEPROM_Read(0x07, u8_Data, &u16_Length) != FUNCTION_OK)
		{
			break;
		}

		DrvEEPROM_Disable();
		DrvEEPROM_Enable();*/
	} 
	while (0);

	while (1)
	{
		;
	}
}

#endif


//Private function definition

void DrvEEPROM_Config(void)
{
	/* Clear frequency bits */
	I2C1->FREQR &= ~I2C_FREQR_FREQ;
	/* Write new value */
	I2C1->FREQR |= DRV_SYSTEM_CLOCK / 1000000;

	/* Disable I2C to configure TRISER */
	I2C1->CR1 &= ~I2C_CR1_PE;

	/* Clear CCRH & CCRL */
	I2C1->CCRH &= ~(I2C_CCRH_FS | I2C_CCRH_DUTY | I2C_CCRH_CCR);
	I2C1->CCRL &= ~I2C_CCRL_CCR;

	/* Set Maximum Rise Time: 300ns max in Fast Mode
	   = [300ns/(1/input_clock.10e6)]+1
	   = [(input_clock * 3)/10]+1 */
	I2C1->TRISER = (uint8)((((DRV_SYSTEM_CLOCK / 1000000) * 3) / 10) + 1);

	/* Write CCR with new calculated value */
	I2C1->CCRL = (uint8)(DRV_SYSTEM_CLOCK / (I2C_CLOCK * 25));
	I2C1->CCRH = ((uint8)((DRV_SYSTEM_CLOCK / (I2C_CLOCK * 25)) >> 8) & 
		I2C_CCRH_CCR) | I2C_CCRH_FS | I2C_CCRH_DUTY;

	I2C1->OARL = EEPROM_DEVICE_ADDRESS;
	I2C1->OARH = (uint8)(((uint16)EEPROM_DEVICE_ADDRESS & 0x0300) >> 7) | 
		I2C_OARH_ADDCONF;

	I2C1->ITR |= (I2C_ITR_LAST | I2C_ITR_DMAEN);

	I2C1->CR1 |= I2C_CR1_PE;

	/* Configure I2C acknowledgement */
	I2C1->CR2 |= I2C_CR2_ACK;
}


uint DrvEEPROM_PollWriteDone(void)
{
	do
	{
		/*!< Send START condition */
		I2C1->CR2 |= I2C_CR2_START;
		m_u16_Timeout = 0;

		/* Test on EEPROM_I2C EV5 and clear it */
		while ((I2C1->SR1 & I2C_SR1_SB) == 0)  /* EV5 */
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				return FUNCTION_FAIL;
			}
		}

		/*!< Send EEPROM address for write */
		I2C1->DR = EEPROM_DEVICE_ADDRESS & ~(0x01);
		m_u16_Timeout = 0;

		/*!< Wait for address aknowledgement */
		while ((I2C1->SR1 & I2C_SR1_ADDR) == 0)
		{
			m_u16_Timeout++;

			if (m_u16_Timeout > EEPROM_TIME_OUT)
			{
				break;
			}
		}
	}
	while ((I2C1->SR1 & I2C_SR1_ADDR) == 0);

	/*!< Clear AF flag */
	I2C1->SR2 &= ~I2C_SR2_AF;

	/*!< STOP condition */
	I2C1->CR2 |= I2C_CR2_STOP;

	return FUNCTION_OK;
}
